﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TIS.Imaging.VCDHelpers;
using TIS.Imaging;
//using HalconDotNet;
using log4net;
using System.Threading;

namespace WHW_NetUtility
{
    class TheImageSourceAcq
    {
        public ICImagingControl IcControl=new ICImagingControl ();
       // public HObject ProcImage;          //转换成的图像
        public bool isHaveImageOK=false;   //是否采集了图像并转换成HObject格式
        //表示视频捕获设备属性的按钮接口，按钮接口允许在属性中调用操作（方法），有一个push方法
        //可以调用由这个接口控制的操作
        public VCDButtonProperty softTrigger;  //软触发属性设置
        private VCDRangeProperty Exposure;      //曝光属性设置
        private VCDPropertyItem TriggerMode;    //VCDPropertyItem提供访问视频捕获设备属性的功能
        public string currentSerial;            //当前选择设备的序列号
        private VCDSwitchProperty TrigEnableSwitch;//触发使用
        private VCDSwitchProperty TriPolarity;//极化设置 上升沿/下降沿
        public VCDAbsoluteValueProperty Trigger_Debounce_Time;//Debounce属性(去抖动)
        log4net.ILog log = log4net.LogManager.GetLogger("图像采集");
        //        private FrameHandlerSink fhs;

        /// <summary>
        /// 初始化相机，选择Devices[0]相机，触发设置为false，并注册断开连接、采集事件等
        /// </summary>
        /// <returns>成功返回true，否则返回false</returns>
        public bool CameraInit(bool isTrigger)
        {
            try
            {
                IcControl.Device= IcControl.Devices[0];      //选择第0号设备
                IcControl.ImageAvailableExecutionMode = EventExecutionMode.MultiThreaded; //多线程执行模式
                IcControl.LiveCaptureContinuous = true;        //设置连续采集模式
                IcControl.LiveDisplayDefault = false;                 //阻止IcControl成像控件自动显示采集流
                IcControl.DeviceTrigger = isTrigger;               //初始化外触发为false

                //黑白相机，设置Y800，彩色相机设置成Y16，不设置此句，图像格式有误（图像缓冲是RGB24），采集的图像会出现条纹
                IcControl.MemoryCurrentGrabberColorformat = TIS.Imaging.ICImagingControlColorformats.ICY800;  
                IcControl.DeviceLost += new System.EventHandler<ICImagingControl.DeviceLostEventArgs>(deviceLostImage);//相机掉线回调
                TriggerMode = IcControl.VCDPropertyItems.FindItem(VCDIDs.VCDID_TriggerMode); //此句可以不用设置
                //获取/设置软触发模式，如果相机不支持软触发，softTrigger为空
                softTrigger = (VCDButtonProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_TriggerMode + ":"+VCDIDs.VCDElement_SoftwareTrigger + ":" + VCDIDs.VCDInterface_Button);
                TrigEnableSwitch = (VCDSwitchProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_TriggerMode + ":" +
                VCDIDs.VCDElement_Value + ":" + VCDIDs.VCDInterface_Switch);//触发开关
                                                                            
                TriPolarity = (VCDSwitchProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_TriggerMode + ":" +
                    VCDIDs.VCDElement_TriggerPolarity + ":" + VCDIDs.VCDInterface_Switch);
                TriPolarity.Switch = false;//极化初始化(上升沿还是下降沿)

                Trigger_Debounce_Time = (VCDAbsoluteValueProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_TriggerMode + ":" +
                VCDIDs.VCDElement_TriggerDebounceTime + ":" + VCDIDs.VCDInterface_AbsoluteValue);//去抖动时间设置
                Trigger_Debounce_Time.Value = 30;//设置去抖时间为30微秒，去抖时间可以做成界面可调式，本程序做成固定式了
                //获取/设置曝光模式
                Exposure = (VCDRangeProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_Exposure, VCDIDs.VCDElement_Value, VCDIDs.VCDInterface_Range);
                //相机采集图像回调，在主界面中，也可以加回调，以满足不同需要
                //              IcControl.ImageAvailable += new EventHandler<ICImagingControl.ImageAvailableEventArgs>(ImageAvailableEvent);
                //IcControl.LiveStart();//开始采集
                Hflip(true);
                //                Vflip(true);
                IcControl.LiveStop();
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), "相机初始化");
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);//ex后面不要加Message，即ex.Message，这样的话，会按INFO输出
                return false;
            }
            
        }

        /// <summary>
        /// 用SN序列号打开相机
        /// </summary>
        /// <param name="icImagingControl1">icImagingControl</param>
        /// <param name="Ctemp">输入的序列号</param>
        /// <returns></returns>
        public bool OpenBySN(string Ctemp)
        {
            string temp = "";
            if (IcControl.Devices.Length > 0)
            {
                foreach (Device Dev in IcControl.Devices)
                {
                    if (Dev.GetSerialNumber(out temp))
                    {
                        if (temp == Ctemp)//判断是否等于指定相机序号
                        {
                            IcControl.Device = Dev.Name; 
                        }
                    }
                }
                if (!IcControl.DeviceValid)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 设置曝光值，如果设置值小于设备最小值，设置到最小值，如果大于设备允许最大值，设置为最大值
        /// 当帧率设置的比较低，如全帧率为120，设置为3.75时，曝光设置无效，原因暂未查明
        /// </summary>
        /// <param name="number">要设置的曝光时间，微秒为单元</param>
        public bool ExposureSetup(int number)
        {
//            stopLive();
            try
            {
                if (number >= Exposure.RangeMin && number <= Exposure.RangeMax)
                {
                    Exposure.Value = number;
                }
                else
                {
                    if (number <= Exposure.RangeMin)
                    {
                        Exposure.Value = Exposure.RangeMin;
                    }
                    else
                    {
                        Exposure.Value = Exposure.RangeMax;
                    }
                }
//                stratLive();
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }            
        }

        /// <summary>
        /// 软触发采集一张图像，如果没有打开触发，会先打开触发开关
        /// </summary>
        /// <returns>成功返回true，否则返回false</returns>
        public bool softTriggerPush()
        {
            
            try
            {

//                ToggleTrigger(true);
                softTrigger.Push();
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }     
        }

        /// <summary>
        /// 载入相机配置文档
        /// </summary>
        /// <param name="path">配置文档路径</param>
        /// <returns>成功载入返回true，否则返回false</returns>
        public bool LoadSetting(string path)
        {  
            try
            {
   //             stopLive(IcControl);
                IcControl.LoadDeviceStateFromFile(path, true);
 //               stratLive();
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq),ex);
                return false;
            }
            

        }

        /// <summary>
        /// 保存相机配置文档
        /// </summary>
        /// <param name="path">配置文档路径</param>
        /// <returns>成功载入返回true，否则返回false</returns>
        public bool SaveSetting(string path)
        {
            try
            {
                stopLive();
                IcControl.SaveDeviceStateToFile(path);
//                stratLive();
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
        }

        /// <summary>
        /// 显示相机属性设置对话框，并将保存到setting.xml文件中
        /// </summary>
        public bool ShowProperties()
        {
            try
            {
                if (IcControl.DeviceValid)
                {
                    IcControl.ShowPropertyDialog();
                    IcControl.SaveDeviceStateToFile("camera.xml"); //设置时，设备必须打开
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
            
        }

        /// <summary>
        /// 相机断开触发事件
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">发送参数</param>
        public void deviceLostImage(object sender,ICImagingControl.DeviceLostEventArgs e)
        {
            Log4Helper.WriteLog(typeof(TheImageSourceAcq), "相机连接断开");
        }

        /// <summary>
        /// 返回当前所有可用相机的序列号数组
        /// </summary>
        /// <returns>相机序列号数组</returns>
        public string[] GetAllSerial()
        {
            
            try
            {
                if (IcControl.Devices.Length>0)
                {
                    string[] serial = new string[IcControl.Devices.Length];

                    for (int i = 0; i < IcControl.Devices.Length; i++)
                    {
                        IcControl.Devices[i].GetSerialNumber(out serial[i]);
                    }
                    return serial;
                }
                else
                {
                    return null;
                }
               
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return null;
            }
        }

        /// <summary>
        /// 根据输入数字来选择相机
        /// </summary>
        /// <param name="deviceNumber">输入数字，最大为相机数量减1</param>
        /// <returns>成功选择返回true，否则返回false</returns>
        public bool UpdateDevice(int deviceNumber)
        {
            try
            {
                if ((IcControl.Devices.Length > 0) && (deviceNumber <= IcControl.Devices.Length))
                {
                    IcControl.Device = IcControl.Devices[deviceNumber];
                    IcControl.Devices[deviceNumber].GetSerialNumber(out currentSerial);
                }
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
            
        }

        /// <summary>
        /// 相机采集回调事件，每采集一张图像，都会触发该事件，在事件中完成图像转换，转换成HObject并out输出
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">事件参数</param>
        public void ImageAvailableEvent(object sender, ICImagingControl.ImageAvailableEventArgs e)
        {
            //    如果采集图像出现条纹，且采集图像内容不正确，则可能是格式错误所致，在MemoryCurrentGrabberColorformat中设置相应格式
            try
            {
                //HOperatorSet.GenImage1(out ProcImage, "byte", e.ImageBuffer.Size.Width, e.ImageBuffer.Size.Height, e.ImageBuffer.GetImageDataPtr());
                isHaveImageOK = true;  //在图像处理程序中，将isHaveImageOK设置为false
     //           FrameType ft= e.ImageBuffer.FrameType;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                isHaveImageOK = false;
            }
            GC.Collect();     //垃圾清理，不然软件内存会一直加大
        }

        /// <summary>
        /// 设置触发采集模式
        /// </summary>
        /// <param name="isOpen">为true时，打开触发模式，为false时，关闭触发模式</param>
        /// <returns></returns>
        public bool ToggleTrigger(bool isOpen)
        {
            try
            {
                if (IcControl.DeviceValid)
                {
                    if (IcControl.DeviceTriggerAvailable)
                    {
                        //if (IcControl.DeviceTrigger!=isOpen)
                        //{
                            if (IcControl.LiveVideoRunning)
                            {
                                IcControl.LiveStop();
 //                               IcControl.DeviceTrigger = isOpen;
                                TrigEnableSwitch.Switch = isOpen;
                                IcControl.LiveStart();
                            }
                            else
                            {
 //                               IcControl.DeviceTrigger = isOpen;
                                TrigEnableSwitch.Switch = isOpen;
                                IcControl.LiveStart();
                            }
                        //}
                        //else
                        //{
                        //    return isOpen; //如果要设置的状态和当前状态一样，返回当前状态
                        //}                        
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
            
        }

        //水平镜像
        public void Hflip(bool flag)
        {
//            IcControl.LiveStop(); //停止取图

            FrameFilter RotateFlipFilter;//生成旋转镜像对象
            RotateFlipFilter = IcControl.FrameFilterCreate("Rotate Flip", "");

            if (RotateFlipFilter == null)
            {
                log.Error("Failed to create RotateFlipFilter");
            }
            else
            {
                IcControl.DeviceFrameFilters.Add(RotateFlipFilter);
            }

            bool flipHorizontal = RotateFlipFilter.GetBoolParameter("Flip H");

            flipHorizontal = flag;

            RotateFlipFilter.SetBoolParameter("Flip H", flipHorizontal);

//            IcControl.LiveStart();//开始取图

        }

        //垂直镜像
        public void Vflip( bool flag)
        {
 //           IcControl.LiveStop(); //停止取图

            FrameFilter RotateFlipFilter;//生成旋转镜像对象
            RotateFlipFilter = IcControl.FrameFilterCreate("Rotate Flip", "");

            if (RotateFlipFilter == null)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), "Failed to create RotateFlipFilter");
            }
            else
            {
                IcControl.DeviceFrameFilters.Add(RotateFlipFilter);
            }

            bool flipHorizontal = RotateFlipFilter.GetBoolParameter("Flip V");

            flipHorizontal = flag;

            RotateFlipFilter.SetBoolParameter("Flip V", flipHorizontal);

//            IcControl.LiveStart();//开始取图
        }

        //旋转
        public void RotateAngle(int Rangle)
        {
            IcControl.LiveStop(); //停止取图

            FrameFilter RotateFlipFilter;//生成旋转镜像对象
            RotateFlipFilter = IcControl.FrameFilterCreate("Rotate Flip", "");

            if (RotateFlipFilter == null)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), "Failed to create RotateFlipFilter");
            }
            else
            {
                IcControl.DeviceFrameFilters.Add(RotateFlipFilter);
            }

            RotateFlipFilter.SetIntParameter("Rotation Angle", Rangle);

            IcControl.LiveStart();//开始取图
        }

        //触发使能
        public void TriEnable()
        {
            TrigEnableSwitch = (VCDSwitchProperty)IcControl.VCDPropertyItems.FindInterface(VCDIDs.VCDID_TriggerMode + ":" +
                VCDIDs.VCDElement_Value + ":" + VCDIDs.VCDInterface_Switch);
        }

        /// <summary>
        /// 开始采集图像
        /// </summary>
        /// <returns>打开成功，返回true,否则返回false</returns>
        public bool stratLive()
        {
            if (IcControl.DeviceValid)
            {
                if (IcControl.LiveVideoRunning)
                {
                    IcControl.LiveStop();
                    Thread.Sleep(100);
                    IcControl.LiveStart();            
                    return true;
                }
                else
                {
                    IcControl.LiveStart();
                    return true;
                }              
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 停止采集
        /// </summary>
        /// <returns>成功返回true,否则返回false</returns>
        public bool stopLive()
        {
            try
            {
                if (IcControl.DeviceValid)
                {
                    if (IcControl.LiveVideoRunning)
                    {
                        Thread.Sleep(200);
                        IcControl.LiveStop();
                        return true;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
           
        }

        /// <summary>
        /// 选择设备，弹出设置选择对话框
        /// </summary>
        public bool SelectDevice()
        {
            try
            {
                if (IcControl.LiveVideoRunning)            //显示采集设备是否运行，即是否用LiveStart打开
                {
                    IcControl.LiveStop();                  //停止采集
                    IcControl.ShowDeviceSettingsDialog();  //打开一个设备选择对话框
                    if (IcControl.DeviceValid)             //当有可用设备并打开的时候，返回true
                    {
                        IcControl.LiveStart();             //开始采集
                    }
                }
                else
                {
                    IcControl.ShowDeviceSettingsDialog();
                }
                TIS_DeviceSettings.SaveSelectedDevice(IcControl);
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }  
        }

        /// <summary>
        /// 保存图像
        /// </summary>
        /// <param name="path">图像要保存的本地路径</param>
        private void SaveImage(string path)
        {
            if (IcControl.DeviceValid)
            {
                // Snap (capture) an image to the memory
                IcControl.MemorySnapImage();
                    // Save the image.
                IcControl.MemorySaveImage(path);
            }
        }

        /// <summary>
        /// 关闭相机，并注销图像回调事件
        /// </summary>
        /// <returns>成功返回true,否则返回false</returns>
        public bool closeCamera()
        {
            stopLive();
            try
            {
    //           IcControl.ImageAvailable -= new EventHandler<ICImagingControl.ImageAvailableEventArgs>(ImageAvailableEvent);
                IcControl.Device = null;
                return true;
            }
            catch (Exception ex)
            {
                Log4Helper.WriteLog(typeof(TheImageSourceAcq), ex);
                return false;
            }
            
        }
    }
}
